package com.geekchique.runningbuddy.util;

import java.io.FileNotFoundException;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.util.Log;

import com.geekchique.runningbuddy.model.Jog;
import com.geekchique.runningbuddy.provider.JogsDBSQL;


public class DBHelperImpl implements IDBHelper{

	private SQLiteDatabase db;
	private static final String TAG = "DBHelper";
	
	public DBHelperImpl(){
		
	}

    public DBHelperImpl(Context ctx) {
    	
        try {
        	db = ctx.openDatabase(JogsDBSQL.DATABASE_NAME, null);
        } catch (FileNotFoundException e) {
            createJoggingEntriesDB(ctx);
        }
    }
    
    public DBHelperImpl(SQLiteDatabase db) {
    	this.db = db;
    }

	public void createJoggingEntriesDB(Context ctx) {
		try {
		    db = ctx.createDatabase(JogsDBSQL.DATABASE_NAME, JogsDBSQL.DATABASE_VERSION, 0, null);
		    db.execSQL(JogsDBSQL.DATABASE_CREATE);
		    Log.i(TAG, "Created new JoggingEntries DB");
		} catch (FileNotFoundException e1) {
		    db = null;
		    Log.e(TAG, "Failed to create new JoggingEntries DB");
		}
	}
    
    public void close() {
        db.close();
    }

    public void addJogEntry(Jog entry) {
    	db.execSQL(JogsDBSQL.insertJogName(entry.name));
    	
    	Cursor c = db.rawQuery(JogsDBSQL.selectJustEnteredJogId(), null);
        c.first();
    	String jogId = c.getString(0);
    	String justEnteredJogId = new String(jogId); 
        
    	db.execSQL(JogsDBSQL.insertRouteJogId(justEnteredJogId));
    	String justEnteredRouteId = c.getString(0); 

        db.execSQL(JogsDBSQL.addATimeEntry(justEnteredJogId, justEnteredRouteId, "1", DBHelperTools.expectedFormat(entry.getStartTime()), "FALSE"));
        db.execSQL(JogsDBSQL.addATimeEntry(justEnteredJogId, justEnteredRouteId, "2", DBHelperTools.expectedFormat(entry.getStopTime()), "FALSE"));
    	
    }
    

    public void updateJogEntry(long Id, Jog entry) {
	        ContentValues args = new ContentValues();
	        args.put(JogsDBSQL.JOG_ID, entry.get_id());
	        args.put(JogsDBSQL.JOG_NAME, entry.getName());
	//        args.put(JogsDBSQL.JOG_START_TIME, entry.getStartTime());
	//        args.put(JogsDBSQL.JOG_STOP_TIME, entry.getStopTime());
	        
	        db.update(JogsDBSQL.JOGGING_ENTRIES_TABLE, args, "id=" + Id, null);
	}
    
    public void deleteJogEntry(long Id) {
    	db.delete(JogsDBSQL.JOGGING_ENTRIES_TABLE, "id=" + Id, null);
    }

	public List<Jog> fetchAllJogEntries(){
        List<Jog> ret = new LinkedList<Jog>();
        Cursor c = db.query(JogsDBSQL.JOGGING_ENTRIES_TABLE, JogsDBSQL.COLUMNS_IN_JOG_ENTRY, null, null, null, null, null);
        
        int numRows = c.count();
        c.first();
        for (int i = 0; i < numRows; ++i) {
            ret.add(new Jog(c.getLong(0), c.getString(1), c.getLong(2), c.getLong(3)));
            c.next();
        }
        
        return ret;
    }
    
    public List<Jog> fetchAllTodaysJogEntries(){
		return getJogsFromCursor(db.rawQuery(JogsDBSQL.FETCH_ALL_TODAYS_JOG_ENTRIES, null));
	}
    
	public List<Jog> fetchAllJogEntries(Integer day, Integer month, Integer year) {
	    return getJogsFromCursor(db.rawQuery(JogsDBSQL.GET_ENTRIES(day, month, year), null));
	}

	public List<Jog> fetchAllThisMonthsJogEntries(Calendar calendar){
		return getJogsFromCursor(db.rawQuery(JogsDBSQL.GET_MONTH_ENTRIES((calendar.get(Calendar.MONTH) + 1), calendar.get(Calendar.YEAR)), null));
    }

	private List<Jog> getJogsFromCursor(Cursor c) {
		int newJogId = 0;
    	int lastRowEnteredJogId = 0;
    	List<Jog> ret = new LinkedList<Jog>();
	    TreeMap<Long, Location> jogTimes = new TreeMap<Long, Location>();
		int numRows = c.count();
		c.first();
		
		
		for (int i = 0; i < numRows; ++i) {
			newJogId = c.getInt(JogsDBSQL.JOGRESULTS_JOG_ID_COL);
			   
			if(newJogId == lastRowEnteredJogId) {
				   jogTimes.put(DBHelperTools.expectedFormat(c.getString(JogsDBSQL.JOGRESULTS_TIME_COL)), getALocation(JogsDBSQL.JOGRESULTS_LONGITUDE_COL, JogsDBSQL.JOGRESULTS_LATITUDE_COL, c));
			}else{
				
				if(jogTimes.size() > 0) {
					ret.add(new Jog(c.getString(JogsDBSQL.JOGRESULTS_NAME_COL), c.getString(JogsDBSQL.JOGRESULTS_ROUTE_ID_COL), jogTimes));
					jogTimes = new TreeMap<Long, Location>();
				}
				
				jogTimes.put(DBHelperTools.expectedFormat(c.getString(JogsDBSQL.JOGRESULTS_TIME_COL)), getALocation(JogsDBSQL.JOGRESULTS_LONGITUDE_COL, JogsDBSQL.JOGRESULTS_LATITUDE_COL, c));
			}
			   
			lastRowEnteredJogId = newJogId;
			   
			if(c.isLast()) {
				ret.add(new Jog(c.getString(JogsDBSQL.JOGRESULTS_NAME_COL), c.getString(JogsDBSQL.JOGRESULTS_ROUTE_ID_COL), jogTimes));
			}
			   
			c.next();
			   
		}
		return ret;
	}

	private Location getALocation(int LONGITUDE_COL, int LATITUDE_COL, Cursor c) {
		Location pointLocation = new Location();
		   pointLocation.setLongitude(c.getInt(LONGITUDE_COL));
		   pointLocation.setLatitude(c.getInt(LATITUDE_COL));
		return pointLocation;
	}
    
    public Jog fetchJogEntry(String id) {
        Jog row = new Jog();
        
	    Cursor c = db.rawQuery(JogsDBSQL.selectAJogEntry(id), null);
        
        if (c.count() > 0) {
            c.first();
            row.set_id(c.getLong(0));
            row.setName(c.getString(1));
            row.setStartTime(c.getLong(2));
            row.setStopTime(c.getLong(3));
            
            return row;
        } else {
            row.set_id(-1);
            row.setName(null);
        }
        return row;
    }

    public Cursor getCursorOfAllJogs() {
		return db.query(JogsDBSQL.JOGGING_ENTRIES_TABLE, JogsDBSQL.COLUMNS_IN_JOG_ENTRY, null, null, null, null, null);
	}

}



